package edu.gatech.wms.controllers;

import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import java.util.Random;

import edu.gatech.wms.models.DBInterface;
import edu.gatech.wms.models.User;

/**
 * 
 * All User Object Related transactions should be handled here
 * 
 */
public abstract class UserManager implements DBInterface {
	
	private static String hashPassword(String _password) {
		
		byte[] encodedPassword = new byte[ 32 ];
		try {
			MessageDigest mySha1 = MessageDigest.getInstance("SHA-256");
			mySha1.update(_password.getBytes());
			encodedPassword = mySha1.digest();
			mySha1.reset();
			
			return String.format("%0" + (encodedPassword.length * 2) + "X",
					new BigInteger(1, encodedPassword));
		} catch (NoSuchAlgorithmException e) {
			
			e.printStackTrace();
		}
		return null;
	}
	
	/**
	 * Creation of a New User in Database
	 * 
	 * @param _firstName
	 *            First name of a New User
	 * @param _lastName
	 *            Last Name of New User
	 * @param _password
	 *            New Users Password (hash?)
	 * @param _contact
	 *            New users email address
	 * @param _admin
	 *            Is this user a admin?
	 * @return created User object
	 */
	public static void createUser(String _firstName, String _lastName,
			String _password, String _contact, boolean _admin) // it takes in 6
																// params (4
																// strings & 2
																// bool)
	{
		// Random rand = new Random(); // Well we should be using the SQL
		// incrementor...
		int userId = new Random().nextInt();
		User user = new User(
				_firstName, _lastName, userId, hashPassword(_password),
				_contact, _admin);
		dbMain.add(user);
		// Not sure why we would return anything here...
		// return dbMain.queryUser(_contact);
		// dbMain.save(user);
	}
	
	/**
	 * Get a list of all existing users ID numbers
	 * 
	 * @return
	 */
	public static List<Integer> getAllUsers() {
		List<Integer> allUserIds = new LinkedList<Integer>();
		Collection<User> allDBUsers = dbMain.queryAllUsers();
		for ( User foo : allDBUsers ) {
			allUserIds.add(foo.getId());
		}
		return allUserIds;
	}
	
	/**
	 * The Users Full Name
	 * 
	 * @param _userID
	 *            Integer of user we want the name of
	 * @return String Full Name of user
	 */
	public static String getUserFullName(int _userID) {
		User usr = dbMain.queryUser(_userID);
		return usr.getFirstName() + " " + usr.getLastName();
	}
	
	/**
	 * 
	 * @param _userID
	 * @return
	 */
	public static List<Integer> getUserOwnedItems(int _userID) {
		return dbMain.queryUser(_userID).getItemsList();
	}
	
	/**
	 * Find out the Users email address
	 * 
	 * @param _userID
	 *            Integer ID number of desired user
	 * @return email address of user
	 */
	public static String getUserContact(int _userID) {
		User usr = dbMain.queryUser(_userID);
		return usr.getContact();
	}
	
	/**
	 * Delete the User from the Database
	 * 
	 * @param _contact
	 *            User Object to be removed from Database
	 * @return Was Data Successfully Deleted? Y/N
	 */
	public static boolean deleteUser(int _userID) {
		if ( _userID != 0 && dbMain.queryUser(_userID).getId() != 0 ) {	
			dbMain.remove(dbMain.queryUser(_userID));
			return true;	
			
		}
		
		return false;
		
		
	}
	
	/**
	 * Make a User an Admin User
	 * 
	 * @param _userID
	 *            ID of user to alter admin status of
	 * @param status
	 *            new desired status
	 */
	public static void setAdmin(int _userID, boolean status) {
		User temp = dbMain.queryUser(_userID);
		temp.setAdmin(status);
		dbMain.save(temp);
	}
	
	/**
	 * Does this userID belong to an Admin Account?
	 * 
	 * @param _userId
	 *            ID of user to alter admin status of
	 * @return boolean if user is an admin or not
	 */
	public static boolean getAdmin(int _userId) {
		return dbMain.queryUser(_userId).getAdmin();
	}
	
	/**
	 * Is this userID locked?
	 * 
	 * @param _userID
	 * @return
	 */
	public static boolean getLockedStatus(int _userID) {
		return dbMain.queryUser(_userID).getLockedStatus();
	}
	
	/**
	 * Reset the Lockout Status for A userID
	 * 
	 * @param _userID
	 */
	public static void resetLockout(int _userID) {
		dbMain.queryUser(_userID).resetLockout();
	}
	
	/**
	 * 
	 * @param foo
	 * @param _firstName
	 * @param _lastName
	 * @param _password
	 * @param _contact
	 * @param _admin
	 */
	public static void updateUser(int _userID, String _firstName,
			String _lastName, String _password, String _contact, boolean _admin) {
		// dbMain.remove(_userID,Database.IDTYPE_USER);
		User alteredUser = new User(
				_firstName, _lastName, _userID, hashPassword(_password),
				_contact, _admin);
		dbMain.save(alteredUser);
		
		// I should probably 1. get, 2. compare then 3. set all altered fields
		// instead of doing this...
		
		// dbMain.save(alteredUser);
	}
	
}